﻿using System;
using System.Collections.Generic;
using HK.Core.Common.Data;
using HK.Core.Pool;
using HK.Core.Utils;
using HK.Editor.Load.Protocol.Data;

namespace HK.Editor.Load.Data
{
    
    [Serializable]
    public class LoadTree : ListJsonData<LoadTree, LoadBranch>, ILoadTree<LoadTree, LoadBranch>
    {
        /// <summary>
        /// 负载Tag
        /// </summary>
        public string PayloadTag => GetType().Name;

        /// <summary>
        /// 宏定义列表
        /// </summary>
        public List<LoadBranch> Branches => list;
        
        /// <summary>
        /// 存在校验
        /// </summary>
        /// <param name="iKey">Key</param>
        /// <param name="oTarget"></param>
        /// <returns></returns>
        public override bool Exist(string iKey, out LoadBranch oTarget)
        {
            oTarget = null;
            if (string.IsNullOrEmpty(iKey) || 0 >= Count) return false;

            var count = Count;
            for (var idx = 0; idx < count; ++idx)
            {
                var loop = list[idx];
                if(null == loop || !loop.Valid || !iKey.Equals(loop.AssetKey) || loop.IsCaller) continue;

                oTarget = loop;
                break;
            }

            var flg = null != oTarget && oTarget.Valid && !oTarget.IsCaller;
            if (!flg)
            {
                oTarget = null;
            }
            return flg;
        }
        
        /// <summary>
        /// 追加加载信息
        /// </summary>
        /// <param name="iBranch">加载数据</param>
        /// <returns>true:追加成功; false:追加失败;</returns>
        public bool AddBranch(LoadBranch iBranch)
        {
            var flg = AddBranch(iBranch.AssetKey, iBranch.Caller, iBranch.From, iBranch.Async,
                iBranch.Size, iBranch.MemorySize, iBranch.CostTime, iBranch.LoadTime);
            ObjectPool<LoadBranch>.Recycle(iBranch);
            return flg;
        }
        
        /// <summary>
        /// 追加加载信息
        /// </summary>
        /// <param name="iAssetKey">AssetKey</param>
        /// <param name="iCaller">调用者</param>
        /// <param name="iFrom">从哪里加载(R:Resource; Ab:Atlas; Atlas:SpriteAtlas;)</param>
        /// <param name="iAsync">true:异步; false:同步;</param>
        /// <param name="iSize">大小(既:文件的物理大小。单位:Byte)</param>
        /// <param name="iMemorySize">运存大小(既:文件的物理大小。单位:Byte)</param>
        /// <param name="iCostTime">加载耗时(开始加载性能测试时，才会有效)</param>
        /// <param name="iLoadTime">加载时间</param>
        /// <returns>true:追加成功; false:追加失败;</returns>
        public bool AddBranch(string iAssetKey, string iCaller, string iFrom,
            bool iAsync, long iSize, long iMemorySize, long iCostTime, long iLoadTime)
        {
            
            if (!Exist(iAssetKey, out var oTarget))
            {
                var assetType = UtilsIo.GetAssetFileTypeByAssetKey(iAssetKey, out var oFileExtension);
                var mainBranch = ObjectPool<LoadBranch>.Pop();
                mainBranch.Id = Count + 1;
                mainBranch.AssetKey = iAssetKey;
                mainBranch.From = iFrom;
                mainBranch.Async = iAsync;
                mainBranch.Size = iSize;
                mainBranch.CostTime = iCostTime;
                mainBranch.LoadTime = iLoadTime;
                mainBranch.Depth = 0;
                mainBranch.ReferenceCount = 1;
                list.Add(mainBranch);
                
                var childBranch = ObjectPool<LoadBranch>.Pop();
                childBranch.Id = Count + 1;
                childBranch.AssetKey = iAssetKey;
                childBranch.Caller = iCaller;
                childBranch.From = iFrom;
                childBranch.Async = iAsync;
                childBranch.MemorySize = iMemorySize;
                childBranch.CostTime = iCostTime;
                childBranch.LoadTime = iLoadTime;
                childBranch.Depth = mainBranch.Depth + 1;
                list.Add(childBranch);
                return true;
            }
            
            // 非实例化调用
            if(string.IsNullOrEmpty(iCaller) || null == oTarget || !oTarget.Valid || oTarget.IsCaller) return false;
            ++oTarget.ReferenceCount;
            
            var childBranch1 = ObjectPool<LoadBranch>.Pop();
            childBranch1.Id = Count + 1;
            childBranch1.AssetKey = iAssetKey;
            childBranch1.Caller = iCaller;
            childBranch1.From = iFrom;
            childBranch1.Async = iAsync;
            childBranch1.MemorySize = iMemorySize;
            childBranch1.CostTime = iCostTime;
            childBranch1.LoadTime = iLoadTime;
            childBranch1.Depth = oTarget.Depth + 1;
            list.Add(childBranch1);
            return true;
        }
        
    }
}
